//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V0.3.1
#include "at24cxx_driver.h"

#ifdef AT24Cxx_Soft_I2C
/**********************驱动初始化配置*********************/
static WHT_Soft_I2C_Cache_t wht_cache;

static void WHT_AT24Cxx_Driver_Init(void)
{
    if (WHT_Soft_I2C_BUS1_Init() != 0)
    {
        /* 总线初始化失败 */
        return;
    }
    wht_cache.Cmd_Count = 1;
}
/**********************驱动初始化配置*********************/

/************************** start read & write *******************************/
static void WHT_AT24Cxx_Driver_Write(uint8_t addr_7bit, uint8_t* const input_buf, uint32_t count)
{
    while (WHT_Soft_I2C_BUS1->Mutex == I2C_Lock)//等待互斥锁成功打开
        vTaskDelay(1);
    wht_cache.Addr_7Bit = addr_7bit;
    wht_cache.Dir = Soft_I2C_Write;
    //wht_cache.Cmd[0] = cmd;
    wht_cache.Buffer = input_buf;
    wht_cache.Buffer_Count = count;

    WHT_Soft_I2C_BUS_OPS.Read_Write(WHT_Soft_I2C_BUS1, &wht_cache);
}
static void WHT_AT24Cxx_Driver_Read(uint8_t addr_7bit, uint8_t* const output_buf, uint32_t count)
{
    while (WHT_Soft_I2C_BUS1->Mutex == I2C_Lock)//等待互斥锁成功打开
        vTaskDelay(1);
    wht_cache.Addr_7Bit = addr_7bit;
    wht_cache.Dir = Soft_I2C_Read;
    //wht_cache.Cmd[0] = cmd;
    wht_cache.Buffer = output_buf;
    wht_cache.Buffer_Count = count;

    WHT_Soft_I2C_BUS_OPS.Read_Write(WHT_Soft_I2C_BUS1, &wht_cache);
}
/************************** end read & write ********************************/
#else
/**********************驱动初始化配置*********************/
static SemaphoreHandle_t Tx_xSemaphore;//二值信号量句柄
static SemaphoreHandle_t Rx_xSemaphore;

static WHT_I2C_Cache_t wht_cache;

static void WHT_Tx_Idle_IT_Callback(void);
static void WHT_Rx_Idle_IT_Callback(void);
static void WHT_AT24Cxx_Driver_Init(void)
{
    if (WHT_I2C_BUS1_Init() != 0)
    {
        /* 总线初始化失败 */
        return;
    }
    wht_cache.Cmd_Count = 1;
    wht_cache.Read_Finish_IT_CB = WHT_Rx_Idle_IT_Callback;
    wht_cache.Write_Finish_IT_CB = WHT_Tx_Idle_IT_Callback;

    Tx_xSemaphore = xSemaphoreCreateBinary();
    Rx_xSemaphore = xSemaphoreCreateBinary();
}
/**********************驱动初始化配置*********************/


/************************** start read & write *******************************/
/*发送空闲中断回调函数*/
static void WHT_Tx_Idle_IT_Callback(void)
{
    BaseType_t xHigherPriorityTaskWoken;

    xSemaphoreGiveFromISR(Tx_xSemaphore, &xHigherPriorityTaskWoken);//释放信号量
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
/*接收空闲中断回调函数*/
static void WHT_Rx_Idle_IT_Callback(void)
{
    BaseType_t xHigherPriorityTaskWoken;

    xSemaphoreGiveFromISR(Rx_xSemaphore, &xHigherPriorityTaskWoken);//释放信号量
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
static void WHT_AT24Cxx_Driver_Write(uint8_t addr_7bit, uint8_t* const input_buf, uint32_t count)
{
    while (WHT_I2C_BUS1->Mutex == I2C_Lock)//等待互斥锁成功打开
        vTaskDelay(1);
    wht_cache.Addr_7Bit = addr_7bit;
    wht_cache.Dir = I2C_Write;
    //wht_cache.Cmd[0] = cmd;
    wht_cache.Buffer = input_buf;
    wht_cache.Buffer_Count = count;

    TickType_t Tick_Count = count * 9 * 1000  / WHT_I2C_BUS1->Config.I2C_Rate_Hz / portTICK_RATE_MS;//单位ms/Tick
    if (Tick_Count)
        WHT_I2C_BUS_OPS.Read_Write_DMA(WHT_I2C_BUS1, &wht_cache);
    else
        WHT_I2C_BUS_OPS.Read_Write_IT(WHT_I2C_BUS1, &wht_cache);
    
    if (WHT_I2C_BUS1->Mutex == I2C_Unlock)//传输结束
    {
        /*用户可以加入判断是否有错误相关代码*/
    }
    else
        xSemaphoreTake(Tx_xSemaphore, portMAX_DELAY);//等待信号量
}
static void WHT_AT24Cxx_Driver_Read(uint8_t addr_7bit, uint8_t* const output_buf, uint32_t count)
{
    while (WHT_I2C_BUS1->Mutex == I2C_Lock)//等待互斥锁成功打开
        vTaskDelay(1);
    wht_cache.Addr_7Bit = addr_7bit;
    wht_cache.Dir = I2C_Read;
    //wht_cache.Cmd[0] = cmd;
    wht_cache.Buffer = output_buf;
    wht_cache.Buffer_Count = count;

    TickType_t Tick_Count = count * 9 * 1000  / WHT_I2C_BUS1->Config.I2C_Rate_Hz / portTICK_RATE_MS;//单位ms/Tick
    if (Tick_Count)
        WHT_I2C_BUS_OPS.Read_Write_DMA(WHT_I2C_BUS1, &wht_cache);
    else
        WHT_I2C_BUS_OPS.Read_Write_IT(WHT_I2C_BUS1, &wht_cache);
    
    if (WHT_I2C_BUS1->Mutex == I2C_Unlock)//传输结束
    {
        /*用户可以加入判断是否有错误相关代码*/
    }
    else
        xSemaphoreTake(Rx_xSemaphore, portMAX_DELAY);//等待信号量
}
/************************** end read & write ********************************/
#endif /*AT24Cxx_Soft_I2C*/


static uint8_t WHT_AT24Cxx_Driver_Scan_I2C_Slave_Count(void)
{
#ifdef AT24Cxx_Soft_I2C
    return WHT_Soft_I2C_BUS_OPS.Scan_Mount_Count(WHT_Soft_I2C_BUS1);
#else
    return WHT_I2C_BUS_OPS.Scan_Mount_Count(WHT_I2C_BUS1);
#endif // AT24Cxx_Soft_I2C
}
static FlagStatus WHT_AT24Cxx_Driver_Busy_State(WHT_AT24Cxx_Addr_enum addr)
{
    WHT_AT24Cxx_Driver_Write(addr, NULL, 0);
#ifdef AT24Cxx_Soft_I2C
    if (WHT_Soft_I2C_BUS1->State != I2C_No_Error)
    {
        vTaskDelay(AT24Cxx_Busy_Over_Time / portTICK_RATE_MS);
        WHT_AT24Cxx_Driver_Write(addr, NULL, 0);
        return WHT_Soft_I2C_BUS1->State == I2C_No_Error ? RESET : SET;
    }
#else
    if (WHT_I2C_BUS1->State != I2C_No_Error)
    {
        vTaskDelay(AT24Cxx_Busy_Over_Time / portTICK_RATE_MS);
        WHT_AT24Cxx_Driver_Write(addr, NULL, 0);
        return WHT_I2C_BUS1->State == I2C_No_Error ? RESET : SET;
    }
#endif // AT24Cxx_Soft_I2C
    return RESET;
}
static void WHT_AT24Cxx_Driver_Write_Page(WHT_AT24Cxx_Addr_enum addr, uint16_t start_addr, uint8_t* buff, uint16_t count)
{
    if (count > AT24Cxx_Page_Byte)
        return;
    if (WHT_AT24Cxx_Driver_Busy_State(addr) == SET)
        return;

    wht_cache.Cmd[0] = start_addr & 0xff;
    WHT_AT24Cxx_Driver_Write(addr | (start_addr >> 8), buff, count);
}
static void WHT_AT24Cxx_Driver_Write_Data(WHT_AT24Cxx_Addr_enum addr, uint8_t* const buffer, uint16_t start_addr, uint16_t count)
{
    uint8_t* datax = buffer;
    uint32_t start_count;//首数据
    uint32_t page_count; //页数据
    uint32_t stop_count; //尾数据

    if ((start_addr + count) > (AT24Cxx_Page_Byte * AT24Cxx_Page_Count))//超出AT24Cxx
        return;
    
    start_count = AT24Cxx_Page_Byte - start_addr % AT24Cxx_Page_Byte;//首页写入个数
    if (count > start_count)
    {
        count -= start_count;
        page_count = count / AT24Cxx_Page_Byte;//满页写入的个数
        stop_count = count % AT24Cxx_Page_Byte;//尾页写入的个数
    }
    else
    {
        start_count = 0;   //首页写入的个数
        page_count = 0;	   //满页写入的个数
        stop_count = count;//尾页写入的个数
    }

    //开始对地址写入数据
    if (start_count)//首页写入个数
    {
        WHT_AT24Cxx_Driver_Write_Page(addr, start_addr, datax, start_count);//写入首页
        start_addr += start_count;
        datax += start_count;
    }
    for (; page_count > 0; page_count--)
    {
        WHT_AT24Cxx_Driver_Write_Page(addr, start_addr, datax, AT24Cxx_Page_Byte);//写入满页
        start_addr += AT24Cxx_Page_Byte;
        datax += AT24Cxx_Page_Byte;
    }
    if (stop_count)//尾页写入个数
    {
        WHT_AT24Cxx_Driver_Write_Page(addr, start_addr, datax, stop_count);//写入尾页
    }
}
static void WHT_AT24Cxx_Driver_Read_Data(WHT_AT24Cxx_Addr_enum addr, uint8_t* const buffer, uint16_t start_addr, uint16_t count)
{
    if ((start_addr + count) > (AT24Cxx_Page_Byte * AT24Cxx_Page_Count))
        return;
    if (WHT_AT24Cxx_Driver_Busy_State(addr) == SET)
        return;

    wht_cache.Cmd[0] = start_addr & 0xff;
    WHT_AT24Cxx_Driver_Read(addr | (start_addr >> 8), buffer, count);
}



static uint8_t AT24Cxx_TRx_Buffer[AT24Cxx_BUFFER_SIZE];

const WHT_AT24Cxx_Driver_t WHT_AT24Cxx_Driver =
{
    .WHT_Init                 = WHT_AT24Cxx_Driver_Init,
    .WHT_TRx_Buffer           = AT24Cxx_TRx_Buffer,
    .WHT_Scan_I2C_Slave_Count = WHT_AT24Cxx_Driver_Scan_I2C_Slave_Count,
    .WHT_Read_Data            = WHT_AT24Cxx_Driver_Read_Data,
    .WHT_Write_Data           = WHT_AT24Cxx_Driver_Write_Data,
};
